//////////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014-present, Egret Technology.
//  All rights reserved.
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Egret nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
//  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
//  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////

import tr = egret.sys.tr;
import TextField = egret.TextField;
import SoundChannel = egret.SoundChannel;
import Timer = egret.Timer;

class Main extends eui.UILayer {


    protected createChildren(): void {
        super.createChildren();

        egret.lifecycle.addLifecycleListener((context) => {
            // custom lifecycle plugin
        })

        egret.lifecycle.onPause = () => {
            egret.ticker.pause();
        }

        egret.lifecycle.onResume = () => {
            egret.ticker.resume();
        }

        //inject the custom material parser
        //注入自定义的素材解析器
        let assetAdapter = new AssetAdapter();
        egret.registerImplementation("eui.IAssetAdapter", assetAdapter);
        egret.registerImplementation("eui.IThemeAdapter", new ThemeAdapter());


        this.runGame().catch(e => {
            console.log(e);
        })
    }

    private async runGame() {
        await this.loadResource()
        this.createGameScene();
        // const result = await RES.getResAsync("description_json")
        // this.startAnimation(result);
        // await platform.login();
        // const userInfo = await platform.getUserInfo();
        // console.log(userInfo);

    }

    private async loadResource() {
        try {
            const loadingView = new LoadingUI(this.stage);
            this.stage.addChild(loadingView);
            await RES.loadConfig("resource/default.res.json", "resource/");
            await this.loadTheme();
            await RES.loadGroup("preload", 0, loadingView);
            // RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE,this)
            this.stage.removeChild(loadingView);
        }
        catch (e) {
            console.error(e);
        }
    }

    private loadTheme() {
        return new Promise((resolve, reject) => {
            // load skin theme configuration file, you can manually modify the file. And replace the default skin.
            //加载皮肤主题配置文件,可以手动修改这个文件。替换默认皮肤。
            let theme = new eui.Theme("resource/default.thm.json", this.stage);
            theme.addEventListener(eui.UIEvent.COMPLETE, () => {
                resolve();
            }, this);

        })
    }


    /**
     * 时间函数
     * @type {number}
     */
    private time: number = 0;

    /**
     * 世界向前移动速度
     * @type {number}
     */
    private speedMoveForward: number = 1;

    /**
     * 地板
     */
    private land: egret.Bitmap;

    /**
     * 障碍物
     * @type {any[]}
     */
    private barriers: egret.Bitmap[] = [];

    /**
     * 小鸟
     * @type {any[]}
     */
    private birds: egret.Bitmap[] = [];

    /**
     * 重力加速度
     * @type {number}
     */
    private static G: number = 9.8;


    /**
     * 点击小鸟产生的加速度
     * @type {number}
     */
    private static A_OF_TAP: number = -80;//点击小鸟的时候向上的加速度


    /**
     * 小鸟当前加速度
     * @type {number}
     */
    private accelerateBird = Main.G;//


    /**
     * 加分标记
     * @type {boolean}
     */
    private isCanScore: boolean = true;

    private score: number = 0;

    private scoreText: TextField = new TextField();

    private soundBack: egret.Sound;

    private soundBackChanel: SoundChannel;

    private soundPoint: egret.Sound;

    private soundFly: egret.Sound;

    private soundDie: egret.Sound;

    private startBtn: egret.Bitmap;


    /**
     * 创建场景界面
     * Create scene interface
     */
    protected createGameScene(): void {
        let backGround = this.createBitmapByName("background_png");
        this.addChild(backGround);
        let stageW = this.stage.stageWidth;
        let stageH = this.stage.stageHeight;
        backGround.width = stageW;
        backGround.height = stageH;

        this.generateBarriers();
        this.generateLand();
        this.generateBirds();

        this.addChild(this.scoreText);
        this.scoreText.width = this.stage.stageWidth;
        this.scoreText.textAlign = egret.HorizontalAlign.CENTER;
        this.scoreText.x = 0;
        this.scoreText.y = 55;
        this.scoreText.text = "0";

        this.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onTouchTap, this);

        this.soundBack = RES.getRes("back_mp3");
        this.soundBackChanel = this.soundBack.play(0, -1);

        this.soundPoint = RES.getRes("point_mp3");
        this.soundFly = RES.getRes("wing_mp3");
        this.soundDie = RES.getRes("die_mp3");

        this.startBtn = this.createBitmapByName("start_button_png");
        this.startBtn.touchEnabled = true;
        this.startBtn.addEventListener("touchTap", this.onButtonClick, this);
        this.startBtn.x = this.stage.stageWidth / 2 - this.startBtn.width / 2;
        this.startBtn.y = this.stage.stageHeight / 2 - this.startBtn.height / 2;

        egret.startTick(this.gameLoop, this);
    }

    private generateBirds() {
        this.birds.push(this.createBitmapByName("birds_json.bird1"));
        this.birds.push(this.createBitmapByName("birds_json.bird2"));
        this.birds.push(this.createBitmapByName("birds_json.bird3"));

        this.birds.forEach((bird) => {
            bird.name = "bird"
            bird.x = 100;
            bird.y = this.stage.stageHeight / 2;
        });
    }

    /**
     * 生成地面
     */
    private generateLand() {
        this.land = this.createBitmapByName("land_png");
        this.addChild(this.land)
        let landH = this.land.height;
        this.land.x = 0;
        this.land.y = this.stage.stageHeight - landH;
    }

    /**
     * 生成障碍物，每次都需要生成两组
     */
    private generateBarriers() {
        if (this.barriers.length >= 4) {
            return;
        }
        let barrierUp = this.createBitmapByName("pie_up_png");
        let barrierDown = this.createBitmapByName("pie_down_png");
        this.addChild(barrierUp);
        this.addChildAt(barrierDown, 1);//避免被覆盖
        //生成一组障碍
        var startX: number = this.stage.stageWidth / 2;
        if (this.barriers.length != 0) {
            startX = this.barriers[this.barriers.length - 1].x
        }
        this.barriers.push(barrierUp);
        this.barriers.push(barrierDown);
        var barrierY = this.randomBarrierUpY();
        barrierUp.y = -barrierY;
        barrierUp.x = startX + this.stage.stageWidth / 2 + barrierUp.width;
        barrierDown.y = barrierUp.height + barrierUp.y + this.stage.stageHeight / 6 + 50;
        barrierDown.x = barrierUp.x;
        //加分状态开启
        this.isCanScore = true;
    }

    /**
     *最上面那个柱子的x
     */
    private randomBarrierUpY(): number {
        return Math.floor(Math.random() * (300 - 100)) + 100;
    }

    /**
     * 游戏循环
     * @param {number} timeStamp
     * @returns {boolean}
     */
    private gameLoop(timeStamp: number): boolean {
        this.moveLand();
        this.moveBarriers();
        this.showBird()
        this.birdsMoveDownWithAccelerate();
        this.birdsHitTest();
        this.time++;
        return true;
    }

    private calcScore(): void {
        this.score++;
        this.soundPoint.play(0, 1)
        this.scoreText.text = this.score.toString();
    }

    /**
     * 移动地板
     */
    private moveLand(): void {
        this.land.x -= this.speedMoveForward;
        if (this.land.x < -(this.land.$bitmapData.width - this.stage.stageWidth)) {//如果快要露馅了
            this.land.x = 0;
        }
    }

    private birdIndex: number = 0;
    private birdShowSpeed: number = 0.2;
    private birdShowIndex: number = 0;

    /**
     * 显示小鸟，从3个里面取一个状态展示
     */
    private showBird(): void {
        let bird = this.getChildByName("bird");
        if (bird) {
            this.removeChild(bird);
        }

        this.birdShowIndex = this.birdShowIndex + this.birdShowSpeed;
        if (this.birdShowIndex >= 2) {
            this.birdShowIndex = 0;
        }
        this.birdIndex = Math.floor(this.birdShowIndex);
        this.addChild(this.birds[this.birdIndex]);
    }


    //todo 碰撞检测，看了哈物理引擎，蛮复杂的，先这样实现
    private birdsHitTest(): void {
        let bird = this.birds[0];//随便取一只鸟检测下就ok了
        let birdBound = {
            left: bird.x,
            top: bird.y,
            right: bird.x + bird.width,
            bottom: bird.y + bird.height
        };
        let isHit: boolean = false;
        isHit = this.isHitWithLand(birdBound);
        if (isHit) {
            this.stopGame();
        }
    }

    private stopGame(): void {
        this.soundDie.play(0, 1);
        this.removeEventListener(egret.TouchEvent.TOUCH_TAP, this.onTouchTap, this);
        this.addChild(this.startBtn);
        this.soundBackChanel.stop();
        egret.stopTick(this.gameLoop, this);
    }

    private isHitWithLand(boundOfBird): boolean {
        if (boundOfBird.bottom > this.land.y) {
            return true;
        } else {
            return this.isHitWithBarrier(boundOfBird);
        }

    }

    private isHitWithBarrier(boundOfBird): boolean {
        for (let barrier of this.barriers) {
            let bound = {
                left: barrier.x,
                top: barrier.y,
                right: barrier.x + barrier.width,
                bottom: barrier.y + barrier.height
            }
            //附带得分逻辑判断
            if (this.isCanScore && boundOfBird.left > bound.right) {
                this.calcScore()
                this.isCanScore = false;
            }
            if (boundOfBird.left > bound.right || boundOfBird.right < bound.left
                || boundOfBird.top > bound.bottom || boundOfBird.bottom < bound.top) {
                //这种情况表示，小鸟在障碍物的左边，右边，上边，下边，是没有撞的情况
            } else {
                return true;
            }
        }
        return false;
    }


    /**
     * 根据加速度模型，移动小鸟
     */
    private birdsMoveDownWithAccelerate(): void {
        this.birds.forEach((bird) => {
            bird.y += this.accelerateBird * this.time * 0.01; //offset is gt△t
        })
    }

    /**
     * 移动障碍物
     */
    private moveBarriers(): void {
        this.barriers.forEach((barrier, index, array) => {
            barrier.x -= this.speedMoveForward;
        })
        if (this.barriers.length >= 2) {
            if (this.barriers[1].x <= -this.barriers[1].width) {
                this.barriers.shift();
                this.barriers.shift();

            }
        }
        this.generateBarriers();
    }

    /**
     * 根据name关键字创建一个Bitmap对象。name属性请参考resources/resource.json配置文件的内容。
     * Create a Bitmap object according to name keyword.As for the property of name please refer to the configuration file of resources/resource.json.
     */
    private createBitmapByName(name: string): egret.Bitmap {
        let result = new egret.Bitmap();
        let texture: egret.Texture = RES.getRes(name);
        result.texture = texture;
        return result;
    }


    /**
     * 点击按钮
     * Click the button
     */
    private onButtonClick(e: egret.TouchEvent) {
        this.soundBackChanel = this.soundBack.play(0, -1);
        this.birds.forEach((bird) => {
            bird.y = this.stage.stageHeight / 2;
        })
        this.time = 0;
        this.score = 0;
        this.scoreText.text = "0";
        this.barriers.forEach((barrier) => {
            this.removeChild(barrier);
        });
        this.barriers = [];
        this.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onTouchTap, this);
        egret.startTick(this.gameLoop, this);
        this.removeChild(this.startBtn);
    }


    private accelerateHandler: number;

    /**
     * 屏幕点击,小鸟运动，这里一句重力加速度模型模拟
     *
     * 小鸟点击一下，有一个瞬间的向上的加速度，随后递减到重力加速度
     */
    private onTouchTap(): void {
        this.time = 0;
        this.soundFly.play(0, 1);
        this.accelerateBird = Main.A_OF_TAP + Main.G;
        clearInterval(this.accelerateHandler)
        this.accelerateHandler = setInterval(() => {
            this.accelerateBird += 10
            if (this.accelerateBird >= Main.G) {
                this.accelerateBird = Main.G;
                clearInterval(this.accelerateHandler)
            }
        }, 50)

    }

}
